Learn Technologies
.NET Core 3.1 WEB API – Entity Framework Core 3.1.7 (part 1)

.NET Core 3.1 WEB API – Entity Framework Core 3.1.7 (part 1)

In this post we’ll go through an example of how to implement create .NET Core Web API project with Entity Framework Core 3.1.7.

Before beginning coding, let’s see together the architecture schema. In fact, we need to create a project which can be used in real companies context. That’s mean, develop in accordance with the rules of the art. Using some best of practices and design patterns.

You can fine more details step by step in my video on YouTube or get all the code source on GitHub.

As you can see below, this is the general architecture that we’ll implement in our Web API Solution.

.NET Web API Architecture

In general, any project is made up of 2 parts: The Presentation Layer called hereafter by PL ( Client Application or the Front End) and Web API.
The Web API is composed of Business Logic Layer (BLL) and Data access Layer (DAL).

This Layer are served by API Controllers and protected by Tokens security system which composed by 2 components called Authorization and Authentication.

<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- Middle In Article -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-3326886530249247"
     data-ad-slot="7484259302"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>

BLL:

As indicated by its name, this layer contains all the business rules. Among the common mistakes, developers put often business rules in API Controllers and this is too bad. The controller only the entry point of HTTP requests.

This layer contains a project called Managers, in which we create manager by group of rules. For example we can create UsersManager. It will contains all the business rules related to users.

DAL:

This layer provides access to the database. It contains the database context and Repositories.

Repository is a design pattern used in order to make CRUD operations on database. In other words, the role of repository is only make operations, which means it doesn’t take care of saving the data. It’s the job of UnitOfWork.

Creation Solution

Let’s begin by creation our solution. It’s organized like the image shows below:

WEB API .NET CORE

First of all, you have to create the UserModel entity, it seems like:

using RefreshToken.Models.Enums;
using System;

namespace RefreshToken.Models.Entities
{
    public class UserModel: BaseModel
    {
        public string FirstName { get; set; }

        public string LastName { get; set; }

        public string Email { get; set; }

        public string Password { get; set; }

        public StatusEnum Status { get; set; }

        public string Token { get; set; }

        public DateTime TokenExpires { get; set; }

        public string RefreshToken { get; set; }
    }
}

Please note that the user class user BaseModel, like parent class. It contains the common properties between all models which can be created like ID, CreatetionDate, ModifcationDate…

using System;
namespace RefreshToken.Models.Entities
{
    public class BaseModel
    {
        public long ID { get; set; }

        public DateTime CreationDate { get; set; }

        public DateTime ModificationDate { get; set; }

        public DateTime? DeleteDate { get; set; }
    }
}

Now, we need to install Entity Framework packages on Context project:

Entity Framework NuGet pagckage

Finally, let’s create the Database Context called RefreshTokenContext:

using Microsoft.EntityFrameworkCore;
using RefreshToken.Models.Entities;

namespace RefreshToken.Context
{
    public class RefreshTokenContext : DbContext
    {
        public RefreshTokenContext(DbContextOptions<RefreshTokenContext> dbContextOptions)
            : base(dbContextOptions)
        {
        }

        public DbSet<UserModel> Users { get; set; }
      
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
        }
    }
}

Create Database

We have done here. Just need to run some power shell commands in Package Manager Console. For more details you can see the tutorial in Microsoft web site

Add-migration First
Update-database

Repository

Repository pattern is a kind of container where data access logic is stored. It hides the details of data access logic from business logic. Which means, we allow business logic to access the data object without having knowledge of underlying data access architecture.

Generic Repository

The idea with this pattern is to have a generic abstract way for the app to work with the data layer.
The methods are based on the CRUD methods; Create, Read, Update and Delete.

So the generic repository looked something like this:

using Microsoft.EntityFrameworkCore;
using RefreshToken.Context;
using RefreshToken.Models.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace Repositories.Common
{
    public class GenericRepository<TEntity> : IGenericRepository<TEntity>
     where TEntity : BaseModel
    {
        protected RefreshTokenContext DbCxt;
        protected DbSet<TEntity> DbSet;


        public GenericRepository(RefreshTokenContext refreshTokenContext)
        {
            DbCxt = refreshTokenContext;
            DbSet = refreshTokenContext.Set<TEntity>();
        }

        public void Delete(object id)
        {
            TEntity entityToDelete = DbSet.Find(id);
            this.Delete(entityToDelete);
        }

        public void Delete(TEntity entityToDelete)
        {
            if (DbCxt.Entry(entityToDelete).State == EntityState.Detached)
            {
                DbSet.Attach(entityToDelete);
            }

            DbSet.Remove(entityToDelete);
        }

        public IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "")
        {
            IQueryable<TEntity> query = DbSet;

            if (filter != null)
            {
                query = query.Where(filter);
            }

            foreach (var includeProperty in includeProperties.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
            {
                query = query.Include(includeProperty);
            }

            if (orderBy != null)
            {
                return orderBy(query).ToList();
            }
            else
            {
                return query.ToList();
            }
        }

        public TEntity GetByID(object id)
        {
            return DbSet.Find(id);
        }

        public long Insert(TEntity entity)
        {
            DbSet.Add(entity);
            return entity.ID;
        }

        public void Update(TEntity entityToUpdate)
        {
            DbSet.Attach(entityToUpdate);
            DbCxt.Entry(entityToUpdate).State = EntityState.Modified;
        }

        public void UpdateAll(IEnumerable<TEntity> entitiesToUpdate)
        {
            foreach (var entity in entitiesToUpdate)
            {
                this.Update(entity);
            }
        }
    }
}

UsersRepository

We still need to specify a repository by entity. In fact, we can use the generic repository in the dependency injection. However, it will make debugging more difficult.

using RefreshToken.Context;
using RefreshToken.Models.Entities;
using Repositories.Common;
using Repositories.Interfaces;

namespace Repositories
{
    public class UsersRepository : GenericRepository<UserModel>, IUsersRepository
    {
        public UsersRepository(RefreshTokenContext refreshTokenContext) :
            base(refreshTokenContext)
        {
        }
    }
}

Managers

In the same way, we’ll make a generic Manager, which contains all the common dependency need by the other managers like the UnitOfWork. So my BaseManager will look like:

  public class BaseManager
    {
        protected IUnitOfWork UnitOfWork { get; }

        public BaseManager(IUnitOfWork unitOfWork)
        {
            this.UnitOfWork = unitOfWork;
        }
    }

For instance, let’s create our UsersManager. It contains all the business rules concerning users.

using Managers.Common;
using Managers.Interfaces;
using RefreshToken.Models.Dtos;
using RefreshToken.Models.Entities;
using RefreshToken.Models.Enums;
using RefreshToken.Tools.Extensions;
using Repositories.Common;
using Repositories.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Managers
{
    public class UsersManager : BaseManager, IUsersManager
    {
        private readonly IUsersRepository usersRepository;

        public UsersManager(IUnitOfWork unitOfWork, IUsersRepository usersRepository)
            : base(unitOfWork)
        {
            this.usersRepository = usersRepository;
        }

        public void Delete(long id)
        {
            usersRepository.Delete(id);
            UnitOfWork.Commit();
        }

        public IEnumerable<UserModel> GetAllUsers()
        {
            return usersRepository.Get(x => x.DeleteDate == null).WithoutPassword();
        }

        public UserModel GetUserByEmail(string email)
        {
            return usersRepository.Get(x => x.Email == email && x.DeleteDate == null).SingleOrDefault().WithoutPassword();
        }

        public long Insert(UserModel userModel)
        {
            userModel.CreationDate = userModel.ModificationDate = DateTime.UtcNow;
            userModel.Status = StatusEnum.Pending;
            usersRepository.Insert(userModel);
            UnitOfWork.Commit();
            return userModel.ID;

        }

        public UserModel Login(LoginDto loginDto)
        {
            if (loginDto == null || string.IsNullOrEmpty(loginDto.Email) || string.IsNullOrEmpty(loginDto.Password))
            {
                return null;
            }

            return usersRepository.Get(x => x.DeleteDate == null && x.Email == loginDto.Email && x.Password == loginDto.Password).SingleOrDefault().WithoutPassword();
        }

        public UserModel Update(UserModel userModel)
        {
            var targetUser = usersRepository.Get(x => x.DeleteDate == null && x.Email == userModel.Email).SingleOrDefault();

            if (targetUser != null)
            {
                userModel.ModificationDate = DateTime.UtcNow;
                userModel.Password = targetUser.Password;
                usersRepository.Update(userModel);
                UnitOfWork.Commit();
                return userModel.WithoutPassword();
            }
            return null;
        }
    }
}

Finally, we nedd only to call this manager by the UsersController. On more thing, don’t forget to declare your managers, repositories and database context in the Startup file like a services.

  public void ConfigureServices(IServiceCollection services)
        {
            var appSettingsSection = Configuration.GetSection("AppSettings");
            var appSettings = appSettingsSection.Get<AppSettings>();

            services.AddControllers();
            services.AddDbContext<RefreshTokenContext>(option =>
           {
               option.UseSqlServer(Configuration.GetConnectionString("RefreshTokenDb"));
           });
            services.AddScoped<IUnitOfWork, UnitOfWork>();
            services.AddScoped<IUsersRepository, UsersRepository>();
            services.AddScoped<IRefreshTokensRepository, RefreshTokensRepository>();

            services.AddScoped<IUsersManager, UsersManager>();
            services.AddScoped<IRefreshTokensManager, RefreshTokensManager>();
            services.Configure<AppSettings>(appSettingsSection);

In conclusion, we just finish setting up the WEB API project with Entity Framework and you have a skeleton that can be used for any project.
In the next tutorial, we will see how to make JWT token authentication.

Follow Me For Updates

Subscribe to my YouTube channel or follow me on Twitter or GitHub to be notified when I post new content.

0 0 votes
Article Rating
Subscribe
Notify of
guest
7 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments

[…] .NET Core 3.1 WEB API – Entity Framework Core 3.1.7 (part 1) […]

Ishmael

Way cool! Some extremely valid points! I appreciate you penning this article plus the rest of the site is also really good.

Sanchez

Remarkable! Its truly remarkable post, I have got much clear idea about from this paragraph.

Veronique

Excellent article. I definitely appreciate this site

Henrik

Hiya very nice website!! Man .. Excellent .. Superb .

Gabriel

I think you have observed some very interesting details, appreciate it for the post.

Caroljean

You have brought up a very great details, appreciate it for the post.

7
0
Would love your thoughts, please comment.x
()
x